﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace car_o_matic
{
    public partial class frmMain : Form
    {
        //updatemanager shizzle
        private readonly UpdateManager updateManager = null;

        // Create the thread object. This does not start the thread.
        //Worker workerObject = new Worker();
        Worker worker = new Worker();

        //make some form objects
        frmAddVehicle frmAddVehicle = new frmAddVehicle();

        public frmMain()
        {
            InitializeComponent();

            // create an objects that will manage our check for update process
            this.updateManager = new UpdateManager(this);
        }

        public void openAddVehicleForm()
        {
            frmAddVehicle.ShowDialog();

            //determine the state of the dialogresult prop
            if (frmAddVehicle.DialogResult == DialogResult.OK)
            {
                if (frmAddVehicle.valid)
                {
                    worker.addVehicle(frmAddVehicle.getVehicle);

                    updateVehicleListbox();
                }
                else
                {
                    //there was an validation error, try again
                    openAddVehicleForm();
                }
            }
        }

        private void updateVehicleListbox()
        {
            //add all vehicles to listbox
            lbVehicles.Items.Clear();

            foreach (Vehicle tmpVehicle in worker.vehicles)
            {
                lbVehicles.Items.Add(tmpVehicle.ToString());
            }
        }

        private void startToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Console.WriteLine("main thread: Starting worker thread...");
            worker.DoWork(40);
        }

        private void stopToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Request that the worker thread stop itself:
            worker.RequestStop();
            Console.WriteLine("main thread: Worker thread has terminated.");

        }

        private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // start the check for update process
            this.updateManager.OnCheckForUpdate();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            // when the app is closing, this will stop the thread that checks for the
            // new version or downloads it
            this.updateManager.StopThread();
        }

        // this method is called when the checkForUpdate finishes checking
        // for the new version. If this method returns true, our checkForUpdate
        // object will download the installer
        public bool OnCheckForUpdateFinished(DownloadedVersionInfo versionInfo)
        {
            if ((versionInfo.error) || (versionInfo.installerUrl.Length == 0) || (versionInfo.latestVersion == null))
            {
                MessageBox.Show(this, "Error while looking for the newest version", "Check for updates", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            // compare the current version with the downloaded version number
            Version curVer = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            if (curVer.CompareTo(versionInfo.latestVersion) >= 0)
            {
                // no new version
                MessageBox.Show(this, "No new version detected", "Check for updates", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                return false;
            }

            // new version found, ask the user if he wants to download the installer
            string str = String.Format("New version found!\nYour version: {0}.\nNewest version: {1}. Do you want to download the new version?", curVer, versionInfo.latestVersion);
            return DialogResult.Yes == MessageBox.Show(this, str, "Check for updates", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        }

        // called after the checkForUpdate object downloaded the installer
        public void OnDownloadInstallerFinished(DownloadInstallerInfo info)
        {
            if (info.error)
            {
                MessageBox.Show(this, "Error while downloading the installer", "Check for updates", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // ask the user if he want to start the installer
            if (DialogResult.Yes != MessageBox.Show(this, "Do you want to install the newest version?", "Check for updates", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
            {
                // it not - remove the downloaded file
                try
                {
                    File.Delete(info.path);
                }
                catch { }
                return;
            }
            // run the installer and exit the app
            try
            {
                Process.Start(info.path);
                this.Close();
            }
            catch (Exception)
            {
                MessageBox.Show(this, "Error while running the installer.", "Check for updates", MessageBoxButtons.OK, MessageBoxIcon.Error);
                try
                {
                    File.Delete(info.path);
                }
                catch { }
                return;
            }
            return;
        }

        //serialize a object list so we can store it binary
        //because interfaces can`t be serialized, only concrete types
        private void Serialize<T>(string filename, T objectToSerialize)
        {
            Stream stream = File.Open(filename, FileMode.Create);
            BinaryFormatter bFormatter = new BinaryFormatter();
            bFormatter.Serialize(stream, objectToSerialize);
            stream.Close();
        }

        private T Deserialize<T>(string filename)
        {
            Stream stream = File.Open(filename, FileMode.Open);
            BinaryFormatter bFormatter = new BinaryFormatter();
            T objectToSerialize = (T)bFormatter.Deserialize(stream);
            stream.Close();
            return objectToSerialize;
        }

        private void vehiclesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Serialize("vehicles.dat", worker.vehicles);
        }


        private void cbFunction0_CheckedChanged(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                worker.vehicles[lbVehicles.SelectedIndex].functions[0] = cbFunction0.Checked;
                worker.vehicles[lbVehicles.SelectedIndex].needsTX = true;
            }
            else
            {
                MessageBox.Show("No vehicle selected");
            }
        }
        
        private void cbFunction1_CheckedChanged(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                worker.vehicles[lbVehicles.SelectedIndex].functions[1] = cbFunction1.Checked;
                worker.vehicles[lbVehicles.SelectedIndex].needsTX = true;
            }
            else
            {
                MessageBox.Show("No vehicle selected");
            }
        }

        private void cbFunction2_CheckedChanged(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                worker.vehicles[lbVehicles.SelectedIndex].functions[2] = cbFunction2.Checked;
                worker.vehicles[lbVehicles.SelectedIndex].needsTX = true;
            }
            else
            {
                MessageBox.Show("No vehicle selected");
            }
        }

        private void cbFunction3_CheckedChanged(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                worker.vehicles[lbVehicles.SelectedIndex].functions[3] = cbFunction3.Checked;
                worker.vehicles[lbVehicles.SelectedIndex].needsTX = true;
            }
            else
            {
                MessageBox.Show("No vehicle selected");
            }
        }

        private void lbVehicles_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                //update checkboxes etc
                cbFunction0.Checked = worker.vehicles[lbVehicles.SelectedIndex].functions[0];
                cbFunction1.Checked = worker.vehicles[lbVehicles.SelectedIndex].functions[1];
                cbFunction2.Checked = worker.vehicles[lbVehicles.SelectedIndex].functions[2];
                //cbFunction3.Checked = worker.vehicles[lbVehicles.SelectedIndex].functions[3];

                name.Text = worker.vehicles[lbVehicles.SelectedIndex].name;
                address.Text = worker.vehicles[lbVehicles.SelectedIndex].address.ToString();
                speed.Value = worker.vehicles[lbVehicles.SelectedIndex].speed;
            }
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                OpenFileDialog open = new OpenFileDialog();
                //filters
                open.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp)|*.jpg; *.jpeg; *.gif; *.bmp";
                if (open.ShowDialog() == DialogResult.OK)
                {
                    worker.vehicles[lbVehicles.SelectedIndex].image = new Bitmap(open.FileName);
                    pictureBox1.Image = worker.vehicles[lbVehicles.SelectedIndex].image;
                }
            }
        }

        private void speed_Scroll(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                worker.vehicles[lbVehicles.SelectedIndex].speed = speed.Value;
                worker.vehicles[lbVehicles.SelectedIndex].needsTX = true;
            }
        }

        private void stop_Click(object sender, EventArgs e)
        {
            if (lbVehicles.SelectedItem != null)
            {
                worker.vehicles[lbVehicles.SelectedIndex].stop = true;
                worker.vehicles[lbVehicles.SelectedIndex].speed = 0;
                speed.Value = 0;
                worker.vehicles[lbVehicles.SelectedIndex].needsTX = true;
            }
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openAddVehicleForm();
        }

        private void stopAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (Vehicle tmpVehicle in worker.vehicles)
            {
                tmpVehicle.stop = true;
                tmpVehicle.speed = 0;
                tmpVehicle.needsTX = true;
            }
            //set speed slider to 0
            speed.Value = 0;
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("Opening or saving the COM database will stop all running vehicles. Do you want to continue?", "Are you sure", MessageBoxButtons.YesNo);
           
            foreach (Vehicle tmpVehicle in worker.vehicles)
            {
                tmpVehicle.stop = true;
                tmpVehicle.speed = 0;
                tmpVehicle.needsTX = true;
            }
            //set speed slider to 0
            speed.Value = 0;

            if (result == DialogResult.Yes)
            {
                SaveFileDialog saveFileDialog1 = new SaveFileDialog();
                saveFileDialog1.Filter = "Car-O-Matic|*.com";
                //"JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif"
                saveFileDialog1.Title = "Save Car-O-Matic database";
                saveFileDialog1.ShowDialog();
                // If the file name is not an empty string open it for saving.
                if (saveFileDialog1.FileName != "")
                {
                    Serialize(saveFileDialog1.FileName, worker);
                }
            }
        }

        private void vehiclesToolStripMenuItem1_Click_1(object sender, EventArgs e)
        {
            worker.vehicles = Deserialize<List<Vehicle>>("vehicles.dat");
            updateVehicleListbox();
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("Opening or saving the COM database will stop all running vehicles. Do you want to continue?", "Are you sure", MessageBoxButtons.YesNo);

            foreach (Vehicle tmpVehicle in worker.vehicles)
            {
                tmpVehicle.stop = true;
                tmpVehicle.speed = 0;
                tmpVehicle.needsTX = true;
            }
            //set speed slider to 0
            speed.Value = 0;

            if (result == DialogResult.Yes)
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "Car-O-Matic|*.com";
                //"JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif"
                openFileDialog.Title = "Save Car-O-Matic database";
                openFileDialog.ShowDialog();
                // If the file name is not an empty string open it for saving.
                if (openFileDialog.FileName != "")
                {
                    worker = Deserialize<Worker>(openFileDialog.FileName);
                    updateVehicleListbox();
                }
            }
        }

    }
}
